package lang

import (
	"jvm/native"
	"jvm/rtda"
	. "jvm/typedef"
	"unsafe"
)

const jlObject = "java/lang/Object"

func init() {
	native.Register(jlObject, "getClass", "()Ljava/lang/Class;", getClass)
	native.Register(jlObject, "hashCode", "()I", hashCode)
	native.Register(jlObject, "clone", "()Ljava/lang/Object;", clone)
}

// public final native Class<?> getClass();
func getClass(frame *rtda.Frame) {
	this := frame.LocalVars().GetRef(0)
	frame.OPStack().PushRef(this.Class().JClass())
}

// public native int hashCode();
func hashCode(frame *rtda.Frame) {
	this := frame.LocalVars().GetRef(0)
	hash := uintptr(unsafe.Pointer(this))
	frame.OPStack().PushInt(I4(hash))
}

// protected native Object clone() throws CloneNotSupportedException;
func clone(frame *rtda.Frame) {
	this := frame.LocalVars().GetRef(0)
	class := this.Class()
	cloneable := class.Loader().LoadClass("java/lang/Cloneable")
	if !class.IsImplements(cloneable) {
		panic("CloneNotSupportedException")
	}
	frame.OPStack().PushRef(this.Clone())
}
